package com.xhs.service.impl;

import com.alibaba.fastjson2.JSON;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.xhs.constant.Constants;
import com.xhs.constant.RedisKeyEnum;
import com.xhs.dto.request.GetUserParam;
import com.xhs.entity.SysUserEntity;
import com.xhs.mapper.SysUserMapper;
import com.xhs.message.Result;
import com.xhs.message.ReturnResult;
import com.xhs.service.RedisService;
import com.xhs.service.SysUserService;
import com.xhs.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.xhs.entity.table.SysUserEntityTableDef.SYS_USER_ENTITY;


@Slf4j
@Service
@CacheConfig(cacheNames = "user")
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserEntity> implements SysUserService {

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private RedisService redisService;

    /**
     * 获取所有的key
     *
     * @return ReturnResult<Object>
     */
    @Override
    public ReturnResult<Object> getKey() {
        List<String> key = redisService.getKey();
        return ReturnResult.success(key);
    }

    /**
     * 保存String类型的数据
     *
     * @return ReturnResult<Object>
     */
    @Override
    public ReturnResult<Object> saveToString() {
        boolean save = redisService.saveToString(RedisKeyEnum.USER_STRING, "2022", 90);
        if (!save) {
            return ReturnResult.build(Result.ADD_ERROR);
        }
        return ReturnResult.success();
    }

    /**
     * 获取string类型的数据
     *
     * @return ReturnResult<Object>
     */
    @Override
    public ReturnResult<Object> getString() {
        String string = redisService.getString(RedisKeyEnum.USER_STRING);
        return ReturnResult.success().setData(string);
    }

    /**
     * 保存list类型的数据
     *
     * @return ReturnResult<Object>
     */
    @Override
    public ReturnResult<Object> saveToList() {
        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("李四");
        list.add("王五");
        list.add("周六");
        boolean save = redisService.saveToString(RedisKeyEnum.USER_LIST, list, 90);
        if (!save) {
            return ReturnResult.build(Result.ADD_ERROR);
        }
        return ReturnResult.success();
    }

    /**
     * 获取List类型的数据
     *
     * @return ReturnResult<Object>
     */
    @Override
    public ReturnResult<Object> getList() {
        String string = redisService.getString(RedisKeyEnum.USER_LIST);
        return ReturnResult.success().setData(string);
    }

    /**
     * 保存map类型的数据
     *
     * @return ReturnResult<Object>
     */
    @Override
    public ReturnResult<Object> saveToMap() {
        Map<String, List<String>> map = new HashMap<>(16);
        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("李四");
        list.add("王五");
        list.add("周六");
        map.put("2021", list);
        boolean saveToMap = redisService.saveToMap(RedisKeyEnum.USER_MAP, map, 90);
        if (!saveToMap) {
            return ReturnResult.build(Result.ADD_ERROR);
        }
        return ReturnResult.success();
    }

    /**
     * 获取map类型的数据
     *
     * @return ReturnResult<Object>
     */
    @Override
    public ReturnResult<Object> getFromMap() {
        Map<Object, Object> map = redisService.getFromMap(RedisKeyEnum.USER_MAP);
        return ReturnResult.success().setData(map);
    }

    /**
     * 删除Key
     *
     * @return ReturnResult<Object>
     */
    @Override
    public ReturnResult<Object> delete() {
        boolean delete = redisService.delete(RedisKeyEnum.USER_STRING);
        if (!delete) {
            return ReturnResult.build(Result.DEL_ERROR);
        }
        return ReturnResult.success();
    }

    /**
     * 保存数据
     *
     * @param name 名字
     * @return ReturnResult<Object>
     */
    @Override
    public ReturnResult<Object> setName(String name) {
        boolean set = redisUtil.set(Constants.USER + name, name, 90);
        if (set) {
            return ReturnResult.build(Result.ADD_SUCCESS);
        }
        return ReturnResult.build(Result.ADD_ERROR);
    }

    /**
     * 根据key删除数据
     *
     * @param key key
     * @return ReturnResult<Object>
     */
    @Override
    public ReturnResult<Object> delKeyByName(String key) {
        Object keyName = redisUtil.get(key);
        if (keyName == null) {
            return ReturnResult.build(Result.NOT_KEY);
        }
        redisUtil.del(key);
        return ReturnResult.build(Result.DEL_SUCCESS);
    }

    /**
     * 查询用户信息
     * // @CacheConfig： 一般配置在类上，指定缓存名称，这个名称是和上面“置缓存管理器”中缓存名称的一致。
     * // @Cacheable： 用于对方法返回结果进行缓存，如果已经存在该缓存，则直接从缓存中获取，缓存的key可以从入参中指定，缓存的 value 为方法返回值。
     * // @CachePut： 无论是否存在该缓存，每次都会重新添加缓存，缓存的key可以从入参中指定，缓存的value为方法返回值，常用作于更新。
     * // @CacheEvict： 用于清除缓存
     * // @Caching： 用于一次性设置多个缓存。
     * Cacheable常用注解配置参数
     * value： 缓存管理器中配置的缓存的名称，这里可以理解为一个组的概念，缓存管理器中可以有多套缓存配置，每套都有一个名称，类似于组名，这个可以配置这个值，选择使用哪个缓存的名称，配置后就会应用那个缓存名称对应的配置。
     * key： 缓存的 key，可以为空，如果指定要按照 SpEL 表达式编写，如果不指定，则缺省按照方法的所有参数进行组合。
     * condition： 缓存的条件，可以为空，使用 SpEL 编写，返回 true 或者 false，只有为 true 才进行缓存。
     * unless： 不缓存的条件，和 condition 一样，也是 SpEL 编写，返回 true 或者 false，为 true 时则不进行缓存。
     *
     * @param param 入参
     * @return ReturnResult<SysUserEntity>
     */
    @Override
    @Cacheable(key = "#param.phone", unless = "#result.data==null")
    public ReturnResult<SysUserEntity> getUserInfo(GetUserParam param) {
        log.info("<------- 查询用户信息入参：{} ------>", JSON.toJSONString(param));
        SysUserEntity userEntity = queryChain()
                .select(SYS_USER_ENTITY.DEFAULT_COLUMNS)
                .from(SYS_USER_ENTITY)
                .where(SYS_USER_ENTITY.IS_DELETED.eq(0))
                .and(SYS_USER_ENTITY.PHONE.like(param.getPhone()))
                .one();
        return ReturnResult.<SysUserEntity>success().setData(userEntity);
    }

}
